import { ArmatureView } from "../views/ArmatureView";
import { Armature } from "../models/Armature";
import { BoneController } from "./BoneController";
import { ModeController, ModeType } from "./mode/ModeController";
import { UIEventHandler } from "./UIEventHandler";
import { Transform } from "../geom/Transform";
import { Slot } from "../models/Slot";
import { DisplayController } from "./DisplayController";
import { DisplayType, ImageDisplay } from "../models/Display";
import { Skin, SkinSlot } from "../models/Skin";
import { ItransformableItem } from "./ITransformableItem";
import { SelectedItemManager } from "./SelectedItemManager";

export class ArmatureController {
    public view: ArmatureView;
    public model: Armature;
    public boneControllers: BoneController[] = [];
    public curBoneController: BoneController | null = null;

    public modeController: ModeController;
    public uiEventHandler: UIEventHandler;
    public hoverItem: ItransformableItem | null = null;
    public displayControllers = new Map<number, DisplayController[]>();
    public curSkin = 0;
    public selectedItemManager: SelectedItemManager;

    constructor(view: ArmatureView, model: Armature) {
        this.view = view;
        this.model = model;
        this.selectedItemManager = new SelectedItemManager(this);
        this.modeController = new ModeController(this);
        //this.skinController = new SkinController(this);
        this.uiEventHandler = new UIEventHandler(this);
    }

    public switchMode(modeType: ModeType): void {
        return this.modeController.switchMode(modeType);
    }

    // public applyMatrix2Bone(localMatrix: Matrix) {
    //     let bone = this.getOperateBone();
    //     if (!bone) {
    //         return;
    //     }

    //     let parent = bone.parent;
    //     if (parent) {
    //         let matrix = Matrix.IDENTITY;
    //         let boneTran = Transform.IDENTITY;
    //         matrix.copyFrom(parent.view.localTransform).append(localMatrix).decompose(boneTran);
    //         bone.view.setTransform(boneTran.position.x, boneTran.position.y, boneTran.scale.x, boneTran.scale.y, boneTran.rotation, boneTran.skew.x, 0);
    //     } else {
    //         let boneTran = Transform.IDENTITY;
    //         localMatrix.decompose(boneTran);
    //         bone.view.setTransform(boneTran.position.x, boneTran.position.y, boneTran.scale.x, boneTran.scale.y, boneTran.rotation, boneTran.skew.x, 0);
    //     }

    //     bone.updateLocalMatrix();
    //     bone.updateSubItems();
    //     this.modeController.updateOperateBar(true);
    // }

    public applyTransform2Item(transform: Transform) {
        let item = this.selectedItemManager.getOperateItem();
        if (!item) {
            return;
        }

        item.transform.copyFrom(transform);
        item.updateMatrixByLocalTransform(1);
        item.updateSubItems();
        this.modeController.updateOperateBar(true);
    }

    public updateBoneLength(length: number) {
        let item = this.selectedItemManager.getOperateItem();
        if (!item || item instanceof DisplayController) {
            return;
        }

        let bone = item as BoneController;
        bone.updateArrowLength(length);
        bone.updateSubItems();
    }

    private _getBoneByName(boneName: string) {
        for (const bone of this.boneControllers) {
            if (bone.name == boneName) {
                return bone;
            }
        }

        return null;
    }

    public hoverItemEnter(boneName: string) {
        let bone = this._getBoneByName(boneName);
        if (bone) {
            bone.hoverEnter();
        }
    }

    public hoverItemLeave(boneName: string) {
        let bone = this._getBoneByName(boneName);
        if (bone) {
            bone.hoverLeave();
        }
    }

    public clickBoneFromUI(boneName: string) {
        this.selectedItemManager.clearSelectedItems();
        let bone = this._getBoneByName(boneName);
        if (bone) {
            this.selectedItemManager.addSelectItem(bone);
        }
        this.modeController.updateOperateBar(true);
    }

    public createSlot(parent: string, name: string = ""): string {
        let boneCtrl = this._getBoneByName(parent);
        if (!boneCtrl) {
            return "";
        }

        const slotModel = new Slot();
        slotModel.parent = parent;
        if (name == "") {
            name = `${boneCtrl.name}${boneCtrl.slotCount}`;
        } else {
            name = this.model.genereateSlotName(name);
        }
        slotModel.name = name;

        //this.model.slot.push(slotModel);
        this.model.addSlot(slotModel);
        boneCtrl.slotCount++;
        return name;
    }

    public createDisplay(path: string, boneName: string, displayName: string, displayType: DisplayType = DisplayType.Image, slot: string = "") {
        //let displayModel = new ImageDisplay();
        if (slot !== "") {
            if (!this.model.checkSlotNameExist(slot)) {
                console.log("slot not exist", slot);
                return;
            }
        } else {
            slot = this.createSlot(boneName, displayName);
        }

        if (this.model.skin.length == 0) {
            let skin = new Skin();
            skin.name = "default";
            this.model.addSkin(skin);
        }

        let skinSlot = this.model.skin[this.curSkin].getSlot(slot);
        if (skinSlot == null) {
            skinSlot = new SkinSlot();
            skinSlot.name = slot;
            this.model.skin[this.curSkin].addSlot(skinSlot);
        }

        let display = new ImageDisplay();
        display.name = displayName;
        display.path = path;
        skinSlot.addDisplay(slot, display);

        let boneCtrl = this._getBoneByName(boneName);
        if (!boneCtrl) {
            return;
        }

        let displayController = new DisplayController(display, path, displayType, boneCtrl);
        let curDisplayCtrls = this.displayControllers.get(this.curSkin);
        if (curDisplayCtrls) {
            //curDisplayCtrls.set(displayName, displayController);
            curDisplayCtrls.unshift(displayController);
        } else {
            this.displayControllers.set(this.curSkin, [displayController]);
        }

        this.view.addChild(displayController.view);
        this.view.addChild(displayController.border);
        displayController.updateMatrixByLocalTransform();

        //
        this.selectedItemManager.clearSelectedItems();
        this.selectedItemManager.addSelectItem(displayController);
    }

    public getRootBoneCtrl() {
        if (this.model.bone[0].length > 0) {
            let boneName = this.model.bone[0].name;
            let boneCtrl = this._getBoneByName(boneName);
            if (boneCtrl) {
                return boneCtrl;
            }
        }

        return null;
    }

    public getCurDisplayList() {
        return this.displayControllers.get(this.curSkin);
    }

    // public getAllItems() {
    //     //TODO 优化
    //     let allItems: ItransformableItem[] = [];
    //     for (const bone of this.boneControllers) {
    //         allItems.push(bone);
    //         for (const display of bone.displayList) {
    //             allItems.push(display);
    //         }
    //     }

    //     return allItems;
    // }

}
